<?php defined('SYSPATH') or die('No direct script access.');

class ORM extends Kohana_ORM {
	
	protected static $_compiled_tables = array();
	
	protected $_pc_table_columns = array();
	
	protected $_pc_table_indexes = array();
	
	protected $_compile_table = TRUE;
	
	protected $_compile_table_exists = NULL;
	
	protected $_compile_table_columns = NULL;
	
	protected $_compile_table_indexes = NULL;
	
	public function __construct($id = NULL)
	{
		if (Kohana::$environment !== Kohana::PRODUCTION)
		{
			$this->_compile_table();

			if ( ! empty($this->_has_many))
			{
				foreach ($this->_has_many as $alias_name => $obj)
				{
					if (isset($obj['through']))
						ORM::factory($obj['through']);
				}
			}
		}
		
		parent::__construct($id);
	}
	
	public function pc_table_columns()
	{
		return $this->_pc_table_columns;
	}
	
	public function pc_table_indexes()
	{
		return $this->_pc_table_indexes;
	}
	
	protected function _compile_table()
	{
		if ($this->_compile_table === TRUE AND ! in_array($this->_table_name, ORM::$_compiled_tables))
		{
			$this->_compile_initialize_table();
			$this->_compile_initialize_table_fields();
			$this->_compile_initialize_table_indexes();
			
			ORM::$_compiled_tables[] = $this->_table_name;
		}
	}
	
	protected function _compile_initialize_table()
	{
		$database = Kohana::$config->load('database.'.Database::$default.'.connection.database');
		$table = Kohana::$config->load('database.'.Database::$default.'.table_prefix').$this->_table_name;
		
		if ($this->_compile_table_exists === NULL)
		{
			$compile_table = DB::query(Database::SELECT, "SHOW TABLES LIKE '{$table}'")->execute()->as_array();
			$this->_compile_table_exists = (empty($compile_table)) ? FALSE : TRUE;
		}
		
		if ($this->_compile_table_exists === TRUE)
		{
			if ($this->_compile_table_columns === NULL)
				$this->_compile_table_columns = DB::query(Database::SELECT, "SHOW COLUMNS FROM `{$database}`.`{$table}`")->execute()->as_array('Field');
			
			if ($this->_compile_table_indexes === NULL)
				$this->_compile_table_indexes = DB::query(Database::SELECT, "SHOW INDEXES FROM `{$database}`.`{$table}`")->execute()->as_array('Key_name');
		}
		elseif ($this->_compile_table_exists === FALSE AND ! empty($this->_pc_table_columns))
		{
			$field = array_keys($this->_pc_table_columns);
			$field = reset($field);
			$options = reset($this->_pc_table_columns);

			DB::query(Database::INSERT, "CREATE TABLE IF NOT EXISTS `{$database}`.`{$table}` (`{$field}` INT NOT NULL) ENGINE = INNODB")->execute();

			$this->_compile_table_columns = DB::query(Database::SELECT, "SHOW COLUMNS FROM `{$database}`.`{$table}`")->execute()->as_array('Field');
			$this->_compile_table_indexes = DB::query(Database::SELECT, "SHOW INDEXES FROM `{$database}`.`{$table}`")->execute()->as_array('Key_name');
			
			$this->_compile_table_exists = TRUE;
		}
	}
	
	protected function _compile_initialize_table_fields()
	{
		if ($this->_compile_table_exists === TRUE)
		{
			$database = Kohana::$config->load('database.'.Database::$default.'.connection.database');
			$table = Kohana::$config->load('database.'.Database::$default.'.table_prefix').$this->_table_name;

			if ( ! empty($this->_pc_table_columns))
			{
				foreach($this->_pc_table_columns as $field => $options)
				{
					if (($reset = array_keys($this->_pc_table_columns)) AND ($reset = reset($reset)) 
						AND ! empty($reset))
					{
						$type = explode('(', $options['type']);
						$type = reset($type);
						$type = trim($type);
						
						switch($type)
						{
							case 'INT':
							case 'INTEGER':
								if ( ! isset($this->_compile_table_columns[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								elseif ($options['type'] != UTF8::strtoupper($this->_compile_table_columns[$field]['Type']))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` CHANGE `{$field}` `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								
								break;

							case 'FLOAT':
								if ( ! isset($this->_compile_table_columns[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								elseif ($options['type'] != UTF8::strtoupper($this->_compile_table_columns[$field]['Type']))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` CHANGE `{$field}` `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								break;

							case 'VARCHAR':
								if ( ! isset($this->_compile_table_columns[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								elseif ($options['type'] != UTF8::strtoupper($this->_compile_table_columns[$field]['Type']))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` CHANGE `{$field}`  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								break;

							case 'TEXT':
								if ( ! isset($this->_compile_table_columns[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								elseif ($options['type'] != UTF8::strtoupper($this->_compile_table_columns[$field]['Type']))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` CHANGE `{$field}`  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								break;

							case 'TIMESTAMP':
								if ( ! isset($this->_compile_table_columns[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								elseif ($options['type'] != UTF8::strtoupper($this->_compile_table_columns[$field]['Type']))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` CHANGE `{$field}`  `{$field}` {$options['type']} NULL DEFAULT NULL")->execute();
								}
								break;
						}
					}
				}
			}
		}
	}
	
	protected function _compile_initialize_table_indexes()
	{
		if ($this->_compile_table_exists === TRUE)
		{
			$database = Kohana::$config->load('database.'.Database::$default.'.connection.database');
			$table = Kohana::$config->load('database.'.Database::$default.'.table_prefix').$this->_table_name;
			
			if ($this->_compile_table_indexes === NULL)
				$this->_compile_table_indexes = DB::query(Database::SELECT, "SHOW INDEXES FROM `{$database}`.`{$table}`")->execute()->as_array('Key_name');
			
			if ( ! empty($this->_pc_table_indexes))
			{
				foreach($this->_pc_table_indexes as $field => $indexes)
				{
					foreach ($indexes as $type => $options)
					{
						switch ($type)
						{
							case 'INDEX':
								if ( ! isset($this->_compile_table_indexes[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD INDEX `{$options['name']}` (  `{$field}` )")->execute();
								}
								elseif ( $this->_compile_table_indexes[$field]['Non_unique'] == 0 )
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` DROP INDEX `{$options['name']}`, ADD INDEX `{$options['name']}` (  `{$field}` )")->execute();
								}
								break;
							
							case 'UNIQUE':
								if ( ! isset($this->_compile_table_indexes[$field]))
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD UNIQUE `{$options['name']}` (  `{$field}` )")->execute();
								}
								elseif ( $this->_compile_table_indexes[$field]['Non_unique'] == 1 )
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` DROP INDEX `{$options['name']}`, ADD UNIQUE `{$options['name']}` (  `{$field}` )")->execute();
								}
								break;

							case 'PRIMARY_KEY':
								if (isset($this->_compile_table_indexes['PRIMARY']))
								{
									DB::query(Database::INSERT, "ALTER TABLE `{$database}`.`{$table}` DROP PRIMARY KEY, ADD PRIMARY KEY (`{$field}`)")->execute();
								}
								else
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}` ADD PRIMARY KEY (  `{$field}` )")->execute();
								}
								
								if (isset($this->_pc_table_columns[$field]['AUTO_INCREMENT']) AND $this->_pc_table_columns[$field]['AUTO_INCREMENT'] === TRUE)
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}`  CHANGE  `{$field}`  `{$field}` {$this->_pc_table_columns[$field]['type']} NULL DEFAULT NULL AUTO_INCREMENT")->execute();
								}
								elseif (isset($this->_pc_table_columns[$field]['AUTO_INCREMENT']) AND $this->_pc_table_columns[$field]['AUTO_INCREMENT'] === FALSE)
								{
									DB::query(Database::INSERT, "ALTER TABLE  `{$database}`.`{$table}`  CHANGE  `{$field}`  `{$field}` {$this->_pc_table_columns[$field]['type']} NULL DEFAULT NULL")->execute();
								}
								
								break;
						}
					}
				}
			}
		}
	}
	
}
